/*
 * Copyright 2008  Telsima Corp.
 * Authors:  Shu Lin <slin@telsima.com>
 */

#ifndef _TW_TYPES_H_
#define _TW_TYPES_H_

#if defined(__JUNOS_RE_SDK__) || defined(__linux__)
#define HAVE_STDINT_H 1
#define HAVE_UNISTD_H 1
#define HAVE_NETINET_IN_H 1
#ifdef __linux__
# define HAVE_NET_ETHERNET_H 1
#endif
#endif

#if (HAVE_STDINT_H == 1)

#include <stdint.h>

typedef int8_t tw_int8_t;
typedef int16_t tw_int16_t;
typedef int32_t tw_int32_t;
typedef int64_t tw_int64_t;

typedef uint8_t tw_uint8_t;
typedef uint16_t tw_uint16_t;
typedef uint32_t tw_uint32_t;
typedef uint64_t tw_uint64_t;

#else

#error TW types need to be defined with <sys/types.h>

#endif /* HAVE_STDINT_H */

#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
/*
 *  This definition of true as NOT false is definitive. :) Making
 *  it '1' can cause problems on stupid platforms.  See articles
 *  on C portability for more information.
 */
#define TRUE (!FALSE)
#endif

typedef int tw_bool;

typedef unsigned long int tw_thread_id_t;
typedef int tw_error_t;
typedef tw_uint64_t tw_count_t;
typedef tw_uint32_t tw_state_t;
typedef tw_int32_t  tw_timer_t;

typedef enum tw_id_type_e
{
    TW_ID_TYPE_NONE = 0,
    TW_ID_TYPE_MAC,
    TW_ID_TYPE_IPv4,
    TW_ID_TYPE_IPv6
} tw_id_type_t;

typedef struct tw_dev_id_s
{
    tw_id_type_t    type;
    tw_uint8_t      id[16];
} tw_dev_id_t, *tw_dev_id_p;

typedef tw_dev_id_t tw_bs_id_t;
typedef tw_dev_id_p tw_bs_id_p;

#define TW_ID_STRLEN                (64)
#define CLSF_STRING_LEN             (256)

/* Telsima DPC DP Action types */
typedef enum tw_dp_action_type_e
{
    TW_DP_DROP = 0,
    TW_DP_PERMIT,
    TW_DP_FORWARD,
    TW_DP_BICAST,
    TW_DP_DHCP_RELAY
} tw_dp_action_type_t;

#if (target_os == linux_gnu)
/* align with rtnetlink type now */
typedef struct tw_stat_s
{
    tw_count_t rx_packets;
    tw_count_t tx_packets;
    tw_count_t rx_bytes;
    tw_count_t tx_bytes;
} tw_stat_t, *tw_stat_p;
#endif

#if (HAVE_NET_IF == 1)
#include <net/if.h>
#define INTF_NAME_SIZE  IF_NAMESIZE
#else
#define INTF_NAME_SIZE  16
#endif


#if (HAVE_UNISTD_H == 1)
#include <unistd.h>
#else
#error Need <unistd.h> for Solaris10
#endif

#if (HAVE_NET_ETHERNET_H == 1) || (HAVE_SYS_ETHERNET_H == 1) || defined(__JUNOS_RE_SDK__)

#if (HAVE_NET_ETHERNET_H == 1)
#  include <net/ethernet.h>
#elif (HAVE_SYS_ETHERNET_H == 1)
#  include <sys/ethernet.h>
#else
  /* Junos SDK does not have ETH_ALEN, <net/ethernet.h> or <sys/ethernet.h> */
#  ifndef ETH_ALEN
#    define ETH_ALEN 6
#  endif

   /* use linux-style 'ether_addr_octet' (instead of freebsd 'octet') */
   struct ether_addr {
       u_char ether_addr_octet[ETH_ALEN];
   };

#endif

typedef struct ether_addr tw_ms_id_t;
typedef struct ether_addr tw_hw_addr_t;
#define TW_MS_ID_LEN    (ETH_ALEN)

#else

#error TW MS Id type needs to be defined with <net/ethernet.h> or <sys/ethernet.h>

#endif /* HAVE_NET_ETHERNET_H */

typedef tw_uint32_t sf_id_t;
typedef tw_uint32_t dp_id_t;
typedef tw_uint32_t gre_key_t;
typedef tw_uint8_t  tw_qos_id_t;
typedef tw_uint16_t tw_pdf_id_t;    /* Packet Data Flow Id */
typedef tw_uint16_t tw_sdf_id_t;    /* Service Data Flow Id */
typedef tw_uint32_t tw_serv_id_t;   /* Service Profile Id */
typedef tw_uint16_t tw_clsf_index_t;    /* Classifier Index */
typedef tw_uint8_t  tw_clsf_pri_t;      /* Classifier Priority */

#if ((NWG_ASN_MAJOR_VERSION==1) && (NWG_ASN_MINOR_VERSION==1))
typedef tw_uint16_t  tw_ak_lifetime_t;   /* AK Lifetime */
#else
typedef tw_uint32_t  tw_ak_lifetime_t;   /* AK Lifetime */
#endif

#if (HAVE_NETINET_IN_H == 1)

#include <netinet/in.h>

typedef struct tw_ipaddr_s {
    int     af; /* address family */
    union {
        struct in_addr  ip4addr;
        struct in6_addr ip6addr; /* maybe defined in missing.h */
    } ipaddr;
} tw_ipaddr_t, *tw_ipaddr_p;

#else
#error <netinet/in.h> is needed
#endif

typedef enum bs_dp_type_e
{
    BS_DP_BRIDGE = 0,
    BS_DP_GRE,
    BS_DP_IPIP,
    BS_DP_TYPE_MAX
} bs_dp_type_t;

/*BS Mixed mode: actually only support BS_MODE_MIXED;
 *define bridge and GRE to keep consistent with MIB file.
 */
typedef enum bs_mode_e
{    
    BS_MODE_BRIDGE = 0,
    BS_MODE_GRE,
    BS_MODE_MIXED,    
    BS_MODE_MAX
} bs_mode_t;

typedef enum ms_mode_e
{
    MS_MODE_DIRECT_IP = 0,
    MS_MODE_SIMPLE_IP,
    MS_MODE_MOBILE_IP,
    MS_MODE_MAX
} ms_mode_t;

typedef tw_uint32_t asnr_id_t;

typedef struct dp_s
{
    bs_dp_type_t    type;
    asnr_id_t       asnr_id;
    tw_uint32_t     i_key;
    tw_uint32_t     o_key;
    tw_ipaddr_t     local;
    tw_ipaddr_t     remote;
} dp_t, *dp_p;

#define min(a,b)    (((a)<(b))?(a):(b))
#define max(a,b)    (((a)>(b))?(a):(b))

/* MS Record can be a real one with all the MS context information but big size
 * or a pseudo type with necessary for carrying function call such as R7 interface */
typedef enum ms_context_type
{
    MS_REAL,
    MS_PSEUDO
} ms_context_type_t;


/* generic comparing function prototype of two buffers */
typedef int (*tw_node_cmp_func)(const void *, const void*);

#endif /* _TW_TYPES_H_ */
